package com.brush.brushcommon.handerl;

import com.brush.brushcommon.dto.Result;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingRequestHeaderException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;

@ControllerAdvice
//顾名思义，@ControllerAdvice就是@Controller 的增强版。@ControllerAdvice主要用来处理全局数据，一般搭配@ExceptionHandler、@ModelAttribute以及@InitBinder使用。
@Slf4j
public class AllExceptionHandler {


    //进行异常处理，处理Exception.class的异常
    @ExceptionHandler(Exception.class)
    @ResponseBody //返回json数据如果不加就返回页面了
    public Result doException(Exception ex) {
        //e.printStackTrace();是打印异常的堆栈信息，指明错误原因，
        // 其实当发生异常时，通常要处理异常，这是编程的好习惯，所以e.printStackTrace()可以方便你调试程序！
        ex.printStackTrace();
        System.out.println(ex.getClass());
        System.out.println(ex.getMessage());
        log.error("出现异常:{}",ex.getClass()+":"+ex.getMessage());
        return Result.fail(9999,ex.getMessage());
    }


    //自定义异常
    @ExceptionHandler(CustomException.class)
    @ResponseBody //返回json数据如果不加就返回页面了
    public Result CustomException(CustomException ex) {
        //e.printStackTrace();是打印异常的堆栈信息，指明错误原因，
        // 其实当发生异常时，通常要处理异常，这是编程的好习惯，所以e.printStackTrace()可以方便你调试程序！
        ex.printStackTrace();
        //自定义的code和msg
        log.error("出现异常:{}",ex.getClass()+":"+ex.getMessage());
        return Result.fail(ex.getCode(),ex.getMsg());
    }


    /**
     * 参数不能为空
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseBody
    public Result bindException(MissingServletRequestParameterException exception) {
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(400, String.format("参数%s不能为空！", exception.getParameterName()));
    }

    /**
     * 缺少参数异常
     * @param exception
     * @return
     */
    @ExceptionHandler(MissingRequestHeaderException.class)
    @ResponseBody
    public Result bindException(MissingRequestHeaderException exception) {
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(400, String.format("参数%s不能为空！",  exception.getHeaderName()));
    }


    /**
     * 请求方式异常
     * @param exception
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public Result bindException(HttpRequestMethodNotSupportedException exception) {
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(400, String.format("请求方式异常",  exception.getMessage()));
    }


    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({SQLException.class})
    @ResponseBody
    public Result handleSQLException(SQLException exception) {
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(400, String.format("服务运行SQLException异常",  exception.getMessage()));
    }


    /**
     * 校验参数异常
     * @param exception
     * @return
     */
    @ExceptionHandler(ValidationException.class)
    @ResponseBody
    public Result bindException(ValidationException exception) {
        if(exception instanceof ConstraintViolationException) {
            return Result.fail(400, String.format("参数%s不能为空！", ((ConstraintViolationException) exception).getConstraintViolations()));
        }
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(400, String.format("参数%s不能为空！", exception.getCause()));
    }



    /**
     * 数据库异常
     * @param
     * @return
     */
    @ExceptionHandler(value = DataAccessException.class)
    @ResponseBody
    public Result repeatException(SQLIntegrityConstraintViolationException exception) {
        log.error("出现异常:{}",exception.getClass()+":"+exception.getMessage());
        return Result.fail(999, exception.getMessage());
    }
}
